<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>Mali OpenCL SDK v1.1.0: 64-bit Integers and Atomics</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">Mali OpenCL SDK v1.1.0
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.2 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Home</span></a></li>
      <li class="current"><a href="pages.html"><span>Help&#160;and&#160;Tutorials</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('long64_bit_integer_tutorial.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">64-bit Integers and Atomics </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>A tutorial to demonstrate the use of the <em>long</em> data type (64-bit integer) including atomics.</p>
<h1><a class="anchor" id="long64BitIntegerIntroduction"></a>
Introduction</h1>
<p>In this tutorial we will look at using the <em>long</em> data types in OpenCL. We will also touch on how and why to use atomics in OpenCL. In the process, we introduce one of the 64-bit atomic extensions that Mali-T600 series GPUs support.</p>
<h2><a class="anchor" id="long64BitIntegerType"></a>
Long Data Type</h2>
<p>In the OpenCL Embedded Profile, 64-bit integer (i.e. long, ulong) types are optional (including the corresponding vector data types and operations). However, Mali-T600 series GPUs implement OpenCL Full Profile, where support for 64-bit integer types is required. 64-bit integers are supported and fully hardware accelerated on Mali-T600 series GPUs.</p>
<p>The <em>long</em> data types are used for calculations that require very large integers. Example use cases include:</p>
<ul>
<li>Fixed point arithmetic.</li>
<li>Encryption/decryption.</li>
<li>Hashing.</li>
<li>64-bit arithmetic.</li>
</ul>
<h2><a class="anchor" id="long64BitIntegerAtomics"></a>
64-bit Atomics</h2>
<p>This tutorial requires atomic operations for accumulating values across kernels. Atomic operations for 32-bit integers are a part of the core OpenCL 1.1 Full Profile and therefore supported by all Full Profile implementations (including Mali-T600 series GPUs). However, we require atomics for 64-bit integers, which is an optional extension in OpenCL 1.1 (<em>cl_khr_int64_base_atomics</em>). All Mali-T600 GPUs implement the extension for 64-bit atomics. </p>
<dl class="section note"><dt>Note</dt><dd>Both 32-bit and 64-bit atomics are optional extensions in the OpenCL Embedded Profile.</dd></dl>
<h1><a class="anchor" id="long64BitIntegerImplementation"></a>
Implementation</h1>
<p>Unless otherwise noted, all code snippets come from <a class="el" href="64__bit__integer_8cl.html">64_bit_integer.cl</a>.</p>
<h2><a class="anchor" id="long64BitIntegerSize"></a>
Image Size</h2>
<p>We have included a 512x512 input bitmap for use with this sample (to keep the size of the installer small). However, you are more likely to see performance improvements (when compared to C code running on a CPU) when larger images are used. There is some start-up overhead associated with using OpenCL. This overhead can outweigh the benefits of parallel processing when the input data sizes are small.</p>
<p>This sample has been coded to allow any input bitmap to be used. Simply change <em>input.bmp</em> in the assets directory of the sample to the input image of your choice. You will see larger calculation performance improvements when larger images are used.</p>
<h2><a class="anchor" id="long64BitInteger"></a>
64-bit Arithmetic</h2>
<p>Some face detection techniques, such as the Robust Real-time Object Detection (Viola and Jones, 2001) framework need to calculate the variance of an example sub-window with this formula:</p>
<p><code>Variance = ((&Sigma; p) / N )<sup>2</sup> - 1/N * &Sigma;(p<sup>2</sup>)</code></p>
<p>Where <em>p</em> is the pixels values and <em>N</em> is the total number of pixels.</p>
<p>For this example, we are only calculating the sum of pixel values and the sum of the pixel values squared. We calculate these values in an OpenCL kernel.</p>
<p>On Mali-T600 series GPUs, we recommend the use of vectors 128-bit wide. For more information about vectorization, see <a class="el" href="hello_world_vector_tutorial.html">Vectorizing your OpenCL code</a>.</p>
<p>If we consider that the maximum pixel value at 8-bits per pixel is 255. Squaring this value (255 * 255 = 65025) fits inside a <em>ushort</em> (16-bit type, maximum value 65535). We use <em>ushort8</em> because 8 * 16-bits = 128-bits, the preferred vector width. See <a class="el" href="hello_world_vector_tutorial.html#helloWorldVectorQuery">Querying for Hardware Support</a> for more information on preferred vector width.</p>
<p>However, the sum of the squares and the sum of pixels can overflow a <em>short</em> and an <em>int</em>. Therefore, we convert them to <em>ulong</em> and sum all the values in the vector until we get a single value that can be added to the accumulator (<em>sumOfPixels</em> and <em>squareOfPixels</em> respectively). </p>
<div class="fragment"><div class="line">    <span class="comment">/* Load 8 pixels (char) and convert them to shorts to calculate the square.*/</span></div>
<div class="line">    ushort8 pixelShort = convert_ushort8(vload8(i, imagePixels));</div>
<div class="line">    <span class="comment">/* Square of 255 &lt; 2 ^ 16. */</span></div>
<div class="line">    ushort8 newSquareShort = pixelShort * pixelShort;</div>
<div class="line"></div>
<div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * Convert original pixel value and the square to longs to sum</span></div>
<div class="line"><span class="comment">     * all the vectors together and add the final values to the</span></div>
<div class="line"><span class="comment">     * respective accumulators.</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    ulong8 pixelLong = convert_ulong8(pixelShort);</div>
<div class="line">    ulong8 newSquareLong = convert_ulong8(newSquareShort);</div>
<div class="line"></div>
<div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * Use vector data type suffixes (.lo and .hi) to get smaller vector types,</span></div>
<div class="line"><span class="comment">     * until we obtain one single value.</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    ulong4 sumLongPixels1 = pixelLong.hi + pixelLong.lo;</div>
<div class="line">    ulong2 sumLongPixels2 = sumLongPixels1.hi + sumLongPixels1.lo;</div>
<div class="line">    ulong sumLongPixels3 = sumLongPixels2.hi + sumLongPixels2.lo;</div>
<div class="line"></div>
<div class="line">    ulong4 sumLongSquares1 = newSquareLong.hi + newSquareLong.lo;</div>
<div class="line">    ulong2 sumLongSquares2 = sumLongSquares1.hi + sumLongSquares1.lo;</div>
<div class="line">    ulong sumLongSquares3 = sumLongSquares2.hi + sumLongSquares2.lo;</div>
</div><!-- fragment --><p> As all the kernels are accessing the accumulators at the same time, memory accessing conflicts can happen. This can lead to race conditions and data being lost.</p>
<p>To avoid this, we use <em>atom_add</em> to add an integer value to a value referenced by a pointer. This guarantees that no other kernel executing on the same device can read or write that memory during the addition operation. Atomic operation also exist for other functions (e.g. multiply, subtract, increment, decrement). This means that this operation becomes very expensive, so we want to use it only when necessary. </p>
<div class="fragment"><div class="line">    atom_add(sumOfPixels, sumLongPixels3);</div>
<div class="line">    atom_add(squareOfPixels, sumLongSquares3);</div>
</div><!-- fragment --><p> To enable <em>atom_add</em> for 64-bit integers, we add this <em>pragma</em> to the kernel code: </p>
<div class="fragment"><div class="line"><span class="preprocessor">#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable</span></div>
</div><!-- fragment --> <h1><a class="anchor" id="long64BitIntegerRunning"></a>
Running the Sample</h1>
<p>From a command prompt in the root of the SDK, run:</p>
<ol type="1">
<li><p class="startli">From a command prompt in the root of the SDK, run:</p>
<div class="fragment"><div class="line">cd samples/64_bit_integer</div>
</div><!-- fragment --> <div class="fragment"><div class="line">make install</div>
</div><!-- fragment --><p class="startli">This compiles the 64-bit integer sample code and copies all the files it needs to run to the bin folder in the root directory of the SDK.</p>
</li>
<li>Copy this folder to the board.</li>
<li><p class="startli">Navigate to the folder on the board and run the 64-bit integer binary:</p>
<div class="fragment"><div class="line">./64_bit_integer</div>
</div><!-- fragment --></li>
<li><p class="startli">You should see output similar to:</p>
<div class="fragment"><div class="line">Profiling information:</div>
<div class="line">Queued time:    0.079ms</div>
<div class="line">Wait time:  0.263749ms</div>
<div class="line">Run time:   0.228437ms</div>
<div class="line">Square of the pixel values = 914239116</div>
<div class="line">Sum of the pixel values = 9365464</div>
</div><!-- fragment --></li>
</ol>
<p>Find solutions for <a class="el" href="common_issues.html">Common Issues</a>.</p>
<h1><a class="anchor" id="long64BitIntegerMoreInformation"></a>
More Information</h1>
<p>For more information have a look at the code in <a class="el" href="64__bit__integer_8cpp.html">64_bit_integer.cpp</a> and <a class="el" href="64__bit__integer_8cl.html">64_bit_integer.cl</a>. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="tutorials.html">Tutorials</a></li>
    <li class="footer">
        <a href="http://www.arm.com/">(C) ARM Ltd. 2013</a>
    </li>
  </ul>
</div>
</body>
</html>
